package org.xxpay.mch.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.HtmlUtils;
import org.xxpay.core.common.annotation.MethodLog;
import org.xxpay.core.common.constant.Constant;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.domain.BizResponse;
import org.xxpay.core.common.domain.XxPayPageRes;
import org.xxpay.core.common.domain.XxPayResponse;
import org.xxpay.core.common.exception.ServiceException;
import org.xxpay.core.entity.PayInterfaceType;
import org.xxpay.core.entity.PayInterfaceTypeTemplate;
import org.xxpay.core.entity.PayPassage;
import org.xxpay.core.entity.PayPassageAccount;
import org.xxpay.mch.common.ctrl.BaseController;
import org.xxpay.mch.common.service.RpcCommonService;
import org.xxpay.mch.config.service.CommonConfigService;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author: dingzhiwei
 * @date: 18/05/04
 * @description: 支付通道账户
 */
@RestController
@RequestMapping(Constant.MCH_CONTROLLER_ROOT_PATH + "/config/pay_passage_account")
public class PayPassageAccountController extends BaseController {

    @Autowired
    private RpcCommonService rpcCommonService;

    @Autowired
    private CommonConfigService commonConfigService;

    @RequestMapping("/list")
    @ResponseBody
    public ResponseEntity<?> list(HttpServletRequest request) {
        judgeRecord(); //校验越权操作
        JSONObject param = getJsonParam(request);
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);
        Integer payPassageId = payPassageAccount.getPayPassageId();
        Byte status = payPassageAccount.getStatus();
        int count = commonService.payPassageAccountService.count(payPassageAccount);
        if(count == 0) return ResponseEntity.ok(XxPayPageRes.buildSuccess());
        boolean isOnlySupplier = StringUtils.isNotEmpty(payPassageAccount.getPsStringVal("isOnlySupplier"));
        List<Map> allList = commonService.payPassageAccountService.selectList((getPageIndex(param) -1) * getPageSize(param), getPageSize(param),payPassageId, status,null,null, isOnlySupplier);
        // 今日
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String todayStart = today + " 00:00:00";
        String todayEnd = today + " 23:59:59";
        List<Map> todayList = commonService.payPassageAccountService.selectList((getPageIndex(param) -1) * getPageSize(param), getPageSize(param),payPassageId, status,todayStart,todayEnd, isOnlySupplier);
        // 昨日
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
        String yesterdayStart = yesterday + " 00:00:00";
        String yesterdayEnd = yesterday + " 23:59:59";
        List<Map> yestdayList = commonService.payPassageAccountService.selectList((getPageIndex(param) -1) * getPageSize(param), getPageSize(param),payPassageId, status,yesterdayStart,yesterdayEnd, isOnlySupplier);
        // 支付接口类型Map
        Map payInterfaceTypeMap = commonConfigService.getPayInterfaceTypeMap();
        // 支付接口Map
        Map payInterfaceMap = commonConfigService.getPayInterfaceMap();
        // 转换前端显示
        List<Map> objects = new LinkedList<>();
        for(Map map : allList) {
            String successRate = ((BigDecimal) map.get("successRate")).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_HALF_UP).toString() + "%";
            map.put("successRate",successRate);
            map.put("IfTypeName", payInterfaceTypeMap.get(map.get("IfTypeCode")));    // 转换接口类型名称
            map.put("IfName", payInterfaceMap.get(map.get("IfCode")));                // 转换支付接口名称
            for (Map todayMap : todayList){
                if (map.get("id").equals( todayMap.get("id"))){
                    map.put("todaySuccessRate", ((BigDecimal) todayMap.get("successRate")).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_HALF_UP).toString() + "%");
                    map.put("todayAmount",todayMap.get("totalAmount"));
                    map.put("todayCount",todayMap.get("totalCount"));
                }
            }
            for (Map yestdayMap : yestdayList){
                if (map.get("id").equals(yestdayMap.get("id"))){
                    map.put("yestdaySuccessRate", ((BigDecimal) yestdayMap.get("successRate")).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_HALF_UP).toString() + "%");
                    map.put("yestdayAmount",yestdayMap.get("totalAmount"));
                    map.put("yestdayCount",yestdayMap.get("totalCount"));
                }
            }
            objects.add(map);
        }
        return ResponseEntity.ok(XxPayPageRes.buildSuccess(objects, count));
    }

    @RequestMapping("/get")
    @ResponseBody
    public ResponseEntity<?> get(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        Integer id = getIntegerRequired(param, "id");
        PayPassageAccount payPassageAccount = judgeRecord(id); //校验越权操作
        return ResponseEntity.ok(XxPayResponse.buildSuccess(payPassageAccount));
    }

    @RequestMapping("/update")
    @ResponseBody
    @MethodLog( remark = "修改支付通道子账户" )
    public ResponseEntity<?> update(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);
        payPassageAccount.setParam(HtmlUtils.htmlUnescape(payPassageAccount.getParam())); //获取转义前的真实的数据

        //查询当前支付通道账号信息
        PayPassageAccount dbPassageAccount = judgeRecord(payPassageAccount.getId()); //校验越权操作
        PayInterfaceType payInterfaceType = commonService.payInterfaceTypeService.findByCode(dbPassageAccount.getIfTypeCode());
        if(payInterfaceType.getMustFromTemplate() == MchConstant.PUB_YES){ //强制使用模板
            PayInterfaceTypeTemplate template = commonService.payInterfaceTypeTemplateService.findById(payPassageAccount.getTemplateId());
            if(template == null) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_FOUND));
            if(template.getStatus() != MchConstant.PUB_YES) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_AVAILABLE));
            //将模板参数赋值到payPassageAccount对象中
            payPassageAccount.setParam(template.getParamTemplate());
            payPassageAccount.setPassageMchId(template.getPassageMchIdTemplate());
        }else{
            payPassageAccount.setTemplateId(0L);
        }

        //通道商户ID发生变化 : 判断通道商户是否存在，避免抛出数据库异常错误
        if(!dbPassageAccount.getPassageMchId().equals(payPassageAccount.getPassageMchId())){
            PayPassageAccount selectRecord = new PayPassageAccount();
            selectRecord.setPayPassageId(dbPassageAccount.getPayPassageId());
            selectRecord.setPassageMchId(payPassageAccount.getPassageMchId());
            if(commonService.payPassageAccountService.count(selectRecord) > 0){
                return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_SERVICE_PASSAGE_MCH_ID_EXISTS));
            }
        }

        int count = commonService.payPassageAccountService.update(payPassageAccount);
        if(count == 1) return ResponseEntity.ok(BizResponse.buildSuccess());
        return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
    }

    @RequestMapping("/updateRisk")
    @ResponseBody
    @MethodLog( remark = "修改支付通道子账户风控规则" )
    public ResponseEntity<?> updateRisk(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);
        judgeRecord(payPassageAccount.getId()); //校验越权操作

        if(payPassageAccount.getRiskMode() != null && payPassageAccount.getRiskMode() == 2) {
            Long maxDayAmount = payPassageAccount.getMaxDayAmount();
            Long maxEveryAmount = payPassageAccount.getMaxEveryAmount();
            Long minEveryAmount = payPassageAccount.getMinEveryAmount();
            // 元转分
            if(maxDayAmount != null) payPassageAccount.setMaxDayAmount(maxDayAmount * 100);
            if(maxEveryAmount != null) payPassageAccount.setMaxEveryAmount(maxEveryAmount * 100);
            if(minEveryAmount != null) payPassageAccount.setMinEveryAmount(minEveryAmount * 100);
        }

        //避免不必要的更新
        payPassageAccount.setAccountName(null);
        payPassageAccount.setPassageMchId(null);
        payPassageAccount.setParam(null);
        payPassageAccount.setTemplateId(null);

        int count = commonService.payPassageAccountService.update(payPassageAccount);
        if(count == 1) return ResponseEntity.ok(BizResponse.buildSuccess());
        return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
    }


    @RequestMapping("/add")
    @ResponseBody
    @MethodLog( remark = "新增支付通道子账户" )
    public ResponseEntity<?> add(HttpServletRequest request) {
        judgeRecord(); //校验越权操作
        JSONObject param = getJsonParam(request);
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);
        payPassageAccount.setParam(HtmlUtils.htmlUnescape(payPassageAccount.getParam())); //获取转义前的真实的数据
        Integer payPassageId = getIntegerRequired(param, "payPassageId");
        PayPassage payPassage = commonService.payPassageService.findById(payPassageId);
        if(payPassage == null) {
            return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_PAY_PASSAGE_NOT_EXIST));
        }

        PayInterfaceType payInterfaceType = commonService.payInterfaceTypeService.findByCode(payPassage.getIfTypeCode());
        if(payInterfaceType.getMustFromTemplate() == MchConstant.PUB_YES){ //强制使用模板
            PayInterfaceTypeTemplate template = commonService.payInterfaceTypeTemplateService.findById(payPassageAccount.getTemplateId());
            if(template == null) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_FOUND));
            if(template.getStatus() != MchConstant.PUB_YES) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_AVAILABLE));
            //将模板参数赋值到payPassageAccount对象中
            payPassageAccount.setParam(template.getParamTemplate());
            payPassageAccount.setPassageMchId(template.getPassageMchIdTemplate());
        }else{
            payPassageAccount.setTemplateId(0L);
        }

        //判断通道商户是否存在，避免抛出数据库异常错误
        PayPassageAccount selectRecord = new PayPassageAccount();
        selectRecord.setPayPassageId(payPassageId);
        selectRecord.setPassageMchId(payPassageAccount.getPassageMchId());
        if(commonService.payPassageAccountService.count(selectRecord) > 0){
            return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_SERVICE_PASSAGE_MCH_ID_EXISTS));
        }

        payPassageAccount.setIfCode(payPassage.getIfCode());            // 设置支付接口代码
        payPassageAccount.setIfTypeCode(payPassage.getIfTypeCode());    // 设置接口类型代码
        payPassageAccount.setPassageRate(payPassage.getPassageRate());  // 设置通道费率
        int count = commonService.payPassageAccountService.add(payPassageAccount);
        if(count == 1) return ResponseEntity.ok(BizResponse.buildSuccess());
        return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
    }

    @RequestMapping("/updateState")
    @ResponseBody
    @MethodLog( remark = "修改支付通道子账户" )
    public ResponseEntity<?> updateAccountState(HttpServletRequest request) {
        judgeRecord(); //校验越权操作
        JSONObject param = getJsonParam(request);
        String IdsParam = getStringRequired(param, "ids");
        Byte state = getByte(param, "state");
        JSONArray ids = JSON.parseArray(IdsParam);
        int count = 0;
        if(ids.size() > 0 ){
            for(Object id: ids){
                PayPassageAccount passageAccount = new PayPassageAccount();
                if (state.equals(MchConstant.PUB_YES)){
                    passageAccount.setId(Integer.valueOf(id.toString()));
                    passageAccount.setStatus(MchConstant.PUB_NO);
                    commonService.payPassageAccountService.update(passageAccount);
                }else {
                    passageAccount.setId(Integer.valueOf(id.toString()));
                    passageAccount.setStatus(MchConstant.PUB_YES);
                    commonService.payPassageAccountService.update(passageAccount);
                }
                count ++;
            }

            if (count <= 0) return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));

            return ResponseEntity.ok(BizResponse.buildSuccess());
        }else {
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
        }
    }

    /** 接口验证 **/
    @RequestMapping("/channelTest")
    @ResponseBody
    public ResponseEntity<?> channelTest(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        Integer id = getIntegerRequired(param, "id");
        judgeRecord(id); //校验越权操作
        String result = rpcCommonService.rpcXxPayPassageTestService.test(id);
        return ResponseEntity.ok(BizResponse.build(result));
    }


    /** 校验账号类型和获取的数据是否合法 **/
    private void judgeRecord(){

        //当前登录用户不属于私有商户
        if(this.getUser().getType() != MchConstant.MCH_TYPE_PRIVATE){
            throw new ServiceException(RetEnum.RET_MCH_PERMISSION_ERROR);
        }
    }

    /** 校验账号类型和获取的数据是否合法 **/
    private PayPassageAccount judgeRecord(Integer recordId){

        //当前登录用户是否属于私有商户
        judgeRecord();

        //判断是否越权查看
        PayPassageAccount record = commonService.payPassageAccountService.findById(recordId);
        if(record == null){
            throw new ServiceException(RetEnum.RET_MCH_PERMISSION_ERROR);
        }

        PayPassage payPassage = commonService.payPassageService.findById(record.getPayPassageId());
        if(payPassage == null || payPassage.getBelongInfoType() != MchConstant.SYSTYPE_MCH || !payPassage.getBelongInfoId().equals(this.getUser().getId())){
            throw new ServiceException(RetEnum.RET_MCH_PERMISSION_ERROR);
        }

        return record;
    }


}
